package com.example.security.assembly;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.userdetails.UserDetails;

/**
 * 提供给ProviderManager
 * ProviderManager 里面有很多Provider
 * SystemAuthenticationProvider 用于处理特定类型的token
 */
@Slf4j
public class SystemAuthenticationProvider implements AuthenticationProvider {

    protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();

    //加载系统内用户
    private SystemUserDetailsService userDetailsService;

    public SystemAuthenticationProvider(SystemUserDetailsService userDetailsService){
        this.userDetailsService = userDetailsService;
    }

    /**
     * 加载出系统内用户 而且进行密码检查
     * @param authentication
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String userName = authentication.getPrincipal().toString();
        UserDetails userDetails = userDetailsService.loadUserByUsername(userName);
        //获取和验证密码
        String password = String.valueOf(authentication.getCredentials());
        if (!userDetailsService.matches(userDetails, password)){
            throw new BadCredentialsException(this.messages.getMessage("AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
        }
        return createSuccessAuthentication(authentication, userDetails);
    }

    /**
     * 是否是指定类型的token
     * @param authentication
     * @return
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return UserPostLoginAuthenticationToken.class.isAssignableFrom(authentication);
    }

    protected Authentication createSuccessAuthentication(Authentication authentication, UserDetails user) {
        UserPostLoginAuthenticationToken result = UserPostLoginAuthenticationToken.authenticated(authentication.getPrincipal(), authentication.getCredentials(), user.getAuthorities());
        result.setDetails(authentication.getDetails());
        return result;
    }
}
